#ifndef BMC_LINUX_LIBRARY_H__
#define BMC_LINUX_LIBRARY_H__
/*
 * GPL
 * Free soft,no warranted
 * We are all in the mud, but some of us are looking at the stars.
 * We are not born for ourselves.
 * Author kofshower@gmail.com
 */
/**
 * @file linux_library_speific.h
 * @Synopsis  Dynamically load shared-library, need link dl and boost filesystem
 * @author Chai JunJun
 * @date 2009-06-11
 */
#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <dlfcn.h>

/*#include <dlfcn.h>

void *dlopen(const char *filename, int flag);

char *dlerror(void);

void *dlsym(void *handle, const char *symbol);

int dlclose(void *handle);

Link with -ldl*/

typedef void* TLHModule_t;
typedef TLInt32 TLStatus;

#ifdef IS_GCC
/* GCC 3.3 and later support the visibility attribute. */
#if (__GNUC__ >= 4) || \
    (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
#define TL_VISIBILITY_DEFAULT __attribute__((visibility("default")))
#else
#define TL_VISIBILITY_DEFAULT
#endif

#ifdef __STRICT_ANSI__
  #define TL_INLINE_SPECIFIER	static __inline
  #define TL_ATTR_NORETURN
#else
  #define TL_INLINE_SPECIFIER	static inline
  #define TL_ATTR_NORETURN	__attribute__ ((noreturn))
#endif

#define TL_EXPORT_DECL_SPECIFIER extern TL_VISIBILITY_DEFAULT
#define TL_EXPORT_DEF_SPECIFIER	extern TL_VISIBILITY_DEFAULT
#define TL_IMPORT_DECL_SPECIFIER extern TL_VISIBILITY_DEFAULT
#endif


TL_INLINE_SPECIFIER string ws2s(const wstring& ws);
TL_INLINE_SPECIFIER wstring s2ws(const string& s);

/* -------------------------------------------------------------------------- */
/** @Synopsis  TLLoadLiraryByName
 *
 * @Param libname posix-style pathname point to so file
 * @Param hModule out param
 *
 * @Returns
 */
/* ---------------------------------------------------------------------------- */
TL_INLINE_SPECIFIER TLStatus TLLoadLiraryByName(const string& libname, TLHModule_t& hModule)
{
    boost::filesystem::path full_path( boost::filesystem::initial_path<boost::filesystem::path>() );
    full_path = boost::filesystem::complete(libname);
    if(!boost::filesystem::exists(full_path) || !boost::filesystem::is_regular(full_path))
        return -1;
    hModule = dlopen(full_path.file_string().c_str(), RTLD_LAZY);
    if(!hModule)
        return -1;
    return 0;
}


/* -------------------------------------------------------------------------- */
/** @Synopsis  function pointer(dynamically load)
 */
/* ---------------------------------------------------------------------------- */

typedef void* TLHandleSym_t;

/* -------------------------------------------------------------------------- */
/** @Synopsis  TLGetProcAddress
 *
 * @Param hModule
 * @Param symname
 * @Param ressym
 *
 * @Returns
 */
/* ---------------------------------------------------------------------------- */
TL_INLINE_SPECIFIER TLStatus TLGetProcAddress(TLHModule_t hModule, const char* symname, TLHandleSym_t *ressym)
{
    char* error;
    dlerror();
    *ressym = (TLHandleSym_t)dlsym(hModule, symname);
    if((error = dlerror()) != NULL)
        return -1;
    return 0;
}

/* -------------------------------------------------------------------------- */
/** @Synopsis  TLUnloadLibrary
 *
 * @Param hModule
 *
 * @Returns
 */
/* ---------------------------------------------------------------------------- */

TL_INLINE_SPECIFIER TLStatus TLUnloadLibrary(TLHModule_t hModule)
{
    return dlclose(hModule);
}

#endif //BMC_LINUX_LIBRARY_H__
